home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Graphics
/
NXPlot3d
/
Source
/
DensView.m.bak
< prev
next >
Wrap
Text File
|
1994-02-07
|
9KB
|
334 lines
/* DensView.m Copyright 1992 Steve Ludtke */
/* This object works by taking passed data and rendering it into an NXImage */
/* which is then composited to the screen as necessary. When the view is */
/* resized, the user coordinate system is reset to unit size. Areas can be */
/* selected by dragging with the mouse. A zoomTo:::: message will be sent to*/
/* the delegate with the resulting area. This view now supports both density*/
/* and simple contour plots (2/94) */
#import "Plot3DView.h"
#import "DensView.h"
#import <stdio.h>
#import <string.h>
#import <libc.h>
#import <math.h>
#import <appkit/appkit.h>
#import <dpsclient/psops.h>
char hex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
extern id NXApp;
float sgn(float x) { if (x>=0) return(1.0); return(0); }
@implementation DensView
-initFrame:(NXRect *)myrect
{
[super initFrame:myrect];
[self setDrawSize:1.0 :1.0]; /* set size and origin so view is a "unit" */
[self setDrawOrigin:0.0 :0.0]; /* coordinate system */
point.y=point.x=0.0; /* origin of image when composited */
buf=NULL;
data=NULL;
image=nil; /* new image is created by -setData::::: */
mode=0;
dmode=DM_DENSITY;
return self;
}
-superviewSizeChanged:(const NXSize *)oldsize
{
[super superviewSizeChanged:oldsize];
[self setDrawSize:1.0 :1.0]; /* fix drawing size */
[self setData:nx :ny :data :minZ :maxZ :rec :rec2]; /* re-render NXImage */
return self;
}
/* essentially all this method has to do is composite the NXImage to the */
/* screen. */
-drawSelf:(NXRect *)rects :(int)rectCount
{
if (buf==NULL||data==NULL||image==nil) {
PSsetgray(NX_WHITE);
NXRectFill(&bounds);
return(self);
}
if (mode) {
DPSWritePostScript(DPSGetCurrentContext(), buf, strlen(buf));
}
else [image composite:NX_COPY toPoint:&point];
return self;
}
/* This method receives data and generates the NXImage */
-setData:(int)Nx :(int)Ny :(float *)Data :(float)MinZ :(float)MaxZ :(NXRect)Rec :(NXRect)Rec2
{
NXStream *str;
static char s[220];
int i,j,k,n,d,sl;
float lev,x[4],y[4],p[4];
/* Make sure our postscript buffer is big enough */
if ((Nx*Ny)>bufs) {
if (buf!=NULL) free(buf);
buf=malloc(Nx*Ny*2+Nx*Ny/20+600);
bufs=Nx*Ny;
}
data=Data;
nx=Nx;
ny=Ny;
minZ=MinZ;
maxZ=MaxZ;
rec=Rec;
rec2=Rec2;
/* Since everything conforms properly, it would be quite easy to */
/* generate an EPS file from this data ... */
sprintf(s,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Origin:0 0\n%%%%BoundingBox: 0 0 %f %f\n%%%%EndComments\n/picstr 1 string def\ngsave\n", frame.size.width,frame.size.height);
strcpy(buf,s);
sprintf(s,"%f %f scale ",frame.size.width,frame.size.height);
strcat(buf,s);
strcat(buf,"1 setgray 0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto fill\n");
if (dmode&DM_DENSITY) {
sprintf(s,"gsave %f %f translate\n",-.5/(float)(nx-1),-.5/(float)(ny-1));
strcat(buf,s);
sprintf(s,"%f %f translate %f %f scale\n",
(rec.origin.x-rec2.origin.x)/rec2.size.width,
(rec.origin.y-rec2.origin.y)/rec2.size.height,
rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
strcat(buf,s);
sprintf(s,"%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop} image\n",nx,ny,nx-1,ny-1);
strcat(buf,s);
i=strlen(buf);
for (n=0; n<(nx*ny); n++) {
if (n%100==0) buf[i++]='\n';
d=255*(data[n]-minZ)/(maxZ-minZ);
if (d>255) d=255;
if (d<0) d=0;
buf[i++]=hex[d>>4];
buf[i++]=hex[d&15];
}
buf[i]=0;
strcat(buf," grestore\n");
}
if (dmode&DM_CONTOUR) {
sprintf(s,"%f %f translate %f %f scale\n",
(rec.origin.x-rec2.origin.x)/rec2.size.width,
(rec.origin.y-rec2.origin.y)/rec2.size.height,
rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
strcat(buf,s);
sl=strlen(buf);
strcat(buf,".002 setlinewidth 0 setgray /m {moveto} def /d {lineto} def\n");
sl=strlen(buf);
lev=(maxZ+minZ)/2.0;
for (lev=(maxZ-minZ)/20.0+minZ; lev<MaxZ; lev+=(maxZ-minZ)/10.0) {
for (i=0; i<nx-1; i++) {
for (j=0; j<ny-1; j++) {
p[0]=data[i+j*nx]-lev;
p[1]=data[i+j*nx+1]-lev;
p[2]=data[i+j*nx+nx]-lev;
p[3]=data[i+j*nx+nx+1]-lev;
if ((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=4
&&((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=0)) {
k=0;
if ((p[0]>0&&p[1]<0)||(p[1]>0&&p[0]<0)) {
x[k]=(p[0]/(p[0]-p[1])+(float)i)/(float)(nx-1);
y[k]=(float)j/(float)(ny-1);
k++;
}
if ((p[2]>0&&p[3]<0)||(p[3]>0&&p[2]<0)) {
x[k]=(p[2]/(p[2]-p[3])+(float)i)/(float)(nx-1);
y[k]=(float)(j+1)/(float)(ny-1);
k++;
}
if ((p[0]>0&&p[2]<0)||(p[2]>0&&p[0]<0)) {
x[k]=(float)i/(float)(nx-1);
y[k]=(p[0]/(p[0]-p[2])+(float)j)/(float)(ny-1);
k++;
}
if ((p[1]>0&&p[3]<0)||(p[3]>0&&p[1]<0)) {
x[k]=(float)(i+1)/(float)(nx-1);
y[k]=(p[1]/(p[1]-p[3])+(float)j)/(float)(ny-1);
k++;
}
if (k==2) {
sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d\n", x[0],y[0],x[1],y[1]);
strcat(buf,s);
sl+=strlen(s);
}
else if (k==4) {
sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d %5.3f %5.3f m %5.3f %5.3f d\n",x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]);
strcat(buf,s);
sl+=strlen(s);
}
}
if (sl>malloc_size(buf)-1000) {
buf=realloc(buf,malloc_size(buf)+20000);
}
}
}
}
strcat(buf,"stroke\n");
}
strcat(buf,"\ngrestore\n");
/* send the postscript we generated to an NXImage. I know this is a messy */
/* way of doing things, but it's leftover from a previous incarnation of */
/* this object and I didn't feel like rewriting it ... */
str=NXOpenMemory(buf,strlen(buf),NX_READONLY);
if (image!=nil) [image free];
image=[NXImage alloc];
image=[image initFromStream:str];
NXClose(str);
/* This is how it used to work */
/*DPSWritePostScript(DPSGetCurrentContext(), buf, i);*/
[self display];
return self;
}
-saveTiff:sender
{
NXStream *stream;
id rep,im2;
NXRect rect = { 0,0,300.0,300.0 };
NXSize size = { 300.0, 300.0 };
im2=[[NXImage alloc] initSize:&size];
[im2 setDataRetained:YES];
rep=[NXBitmapImageRep alloc];
[rep initData:NULL pixelsWide:320 pixelsHigh:320 bitsPerSample:8 samplesPerPixel:3 hasAlpha:NO isPlanar:NO colorSpace:NX_RGBColorSpace bytesPerRow:960 bitsPerPixel:24];
[im2 useRepresentation:rep];
/*[im2 useCacheWithDepth:NX_TwentyFourBitRGBDepth];
rep=[im2 lastRepresentation];
[rep setAlpha:NO];*/
[im2 lockFocus];
/*[image composite:NX_COPY toPoint:&rect.origin];*/
PSsetgray(.5);
PSmoveto(0,0);
PSlineto(100.0,100.0);
PSlineto(0,100.0);
PSstroke();
[im2 unlockFocus];
/*printf("Alpha:%d bits:%d colors:%d\n",[rep hasAlpha],[rep bitsPerSample],[rep numColors]);*/
if (image==nil) return self;
stream=NXOpenMemory(NULL,0,NX_WRITEONLY);
[im2 writeTIFF:stream allRepresentations:YES];
NXSaveToFile(stream,"/users/steve/test.tiff");
NXClose(stream);
[im2 free];
return self;
}
-savePS:sender
{
FILE *out;
out=fopen("/users/steve/test.eps","w");
fwrite(buf,strlen(buf),1,out);
fclose(out);
return self;
}
/* Allows the user to select an area of the plot to be passed to the */
/* delegate via a zoomTo:::: message. */
-mouseDown:(NXEvent *)oevent
{
int oldMask,loop=1;
NXEvent *event,evs;
float f,dash[2] = { SS,SS };
evs=*oevent;
oevent=&evs;
[self convertPoint:&oevent->location fromView:nil];
oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
while (loop) {
event = [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
[self convertPoint:&event->location fromView:nil];
switch (event->type) {
case NX_LMOUSEUP:
loop = 0;
if (event->location.x<oevent->location.x) {
f=event->location.x;
event->location.x=oevent->location.x;
oevent->location.x=f;
}
if (event->location.y<oevent->location.y) {
f=event->location.y;
event->location.y=oevent->location.y;
oevent->location.y=f;
}
if (event->location.x-oevent->location.x<.02) break;
if (event->location.y-oevent->location.y<.02) break;
[delegate zoomTo:oevent->location.x :oevent->location.y :event->location.x :event->location.y];
break;
case NX_LMOUSEDRAGGED:
[self lockFocus];
PSsetlinewidth(0.0);
[image composite:NX_COPY toPoint:&point];
PSmoveto(oevent->location.x,oevent->location.y);
PSlineto(event->location.x,oevent->location.y);
PSlineto(event->location.x,event->location.y);
PSlineto(oevent->location.x,event->location.y);
PSlineto(oevent->location.x,oevent->location.y);
PSsetgray(1.0);
PSsetdash(dash,2,0.0);
PSgsave();
PSstroke();
PSgrestore();
PSsetgray(0.0);
PSsetdash(dash,2,SS);
PSstroke();
[self unlockFocus];
[window flushWindow];
break;
}
}
[window setEventMask:oldMask];
return self;
}
-setDenFlag:sender
{
dmode=0;
if ([[sender cellAt:0 :0] intValue]) dmode+=DM_DENSITY;
if ([[sender cellAt:1 :0] intValue]) dmode+=DM_CONTOUR;
[self setData:nx :ny :data :minZ :maxZ :rec :rec2]; /* re-render NXImage */
return self;
}
-(int)acceptsFirstMouse {
return (YES);
}
-printPSCode:sender
{
mode=1;
[self setDrawSize:frame.size.width :frame.size.height];
[super printPSCode:sender];
[self setDrawSize:1.0 :1.0]; /* set size and origin so view is a "unit" */
mode=0;
return self;
}
@end